package com.noahsloan.nutils.collections;

import java.util.HashMap;
import java.util.Map;

import com.noahsloan.nutils.function.Function1;

/**
 * Utility for programmatically constructing a map.
 * 
 * @author noah
 * 
 * @param <K>
 * @param <V>
 */
public class MapBuilder<K, V> {
	
	private final Map<K, V> map;

	public MapBuilder(final Map<K, V> map) {
		super();
		this.map = map;
	}

	public static <K, V> MapBuilder<K, V> putFirst(K key, V value) {
		return new MapBuilder<K, V>(new HashMap<K, V>()).put(key, value);
	}

	public MapBuilder<K, V> put(K key, V value) {
		map.put(key, value);
		return this;
	}

	/**
	 * Splits s as many times as possible on del1, then splits each resulting
	 * string into at most 2 strings on del2. The pairs are then put into a map
	 * which is returned.
	 * 
	 * @param s
	 * @param del1
	 * @param del2
	 * @return
	 */
	public static Map<String, String> splitToMap(String s, String del1,
			String del2) {
		String[] split1 = s.split(del1);
		Map<String, String> map = new HashMap<String, String>(split1.length);
		for (String term : split1) {
			String[] split = term.split(del2, 2);
			map.put(get(split, 0), get(split, 1));
		}

		return map;
	}

	private static <T> T get(T[] array, int i) {
		return i >= array.length ? null : array[i];
	}

	public Map<K, V> getMap() {
		return map;
	}

	/**
	 * Creates a map of the given items, using the given {@link Function1} to
	 * derive the key for each.
	 * 
	 * @param <K>
	 * @param <V>
	 * @param items
	 * @param propertyClass
	 * @param property
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<K, V> mapByProperty(Iterable<V> items,
			Function1<V, K, RuntimeException> function) {
		Map<K, V> map = new HashMap<K, V>();
		for (V v : items) {
			map.put(function.apply(v), v);
		}
		return map;
	}

}
